package com.karrim.server.io;

import com.karrim.server.util.Util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;

/**
 *
 * @author andrea.cantafio
 */
public class CompilingClassLoader extends ClassLoader {

    public CompilingClassLoader() {
        super();
    }

    private boolean compile(String filepath) throws FileNotFoundException {
        File f = new File(filepath);
        if (!f.exists()) {
            throw new FileNotFoundException("File " + f.getAbsolutePath() + " not found!");
        }
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        return compiler.run(null, new FileOutputStream(new File(Util.ABS_PATH + filepath.replace("\\", "."))), null, filepath) == 0;
    }

    private boolean compile(String... filepaths) throws FileNotFoundException {
        boolean result = true;
        for (int i = 0; i < filepaths.length; i++) {
            result &= compile(filepaths[i]);
        }
        return result;
    }

    /*@Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        for (Class<?> clazz : loadedClasses) {
            if (name.equals(clazz.getCanonicalName())) {
                return clazz;
            }
        }
        name = name.replace(".", "\\");
        File source = new File(SOURCE_ABS_PATH + name + ".java");
        File cl = new File(CLASS_PATH + "\\" + name + ".class");
        if (source.exists() && (!cl.exists() || (cl.exists() && (cl.lastModified() < source.lastModified())))) {
            try {
                if (compile(SOURCE_ABS_PATH + "\\" + name + ".java")) {
                    FileInputStream fis;
                    try {
                        fis = new FileInputStream(cl);
                        byte[] content = new byte[fis.available()];
                        fis.read(content);
                        return defineClass(name, content, 0, content.length);
                    } catch (IOException ex) {
                        Logger.getLogger(CompilingClassLoader.class.getName()).log(Level.SEVERE, null, ex);
                        throw new ClassNotFoundException("An error has occurred while reading class file " + cl.getAbsolutePath() + ".");
                    }
                } else {
                    throw new ClassNotFoundException("An error has occurred while compiling " + source.getAbsolutePath() + ".");
                }
            } catch (FileNotFoundException ex) {
                throw new ClassNotFoundException();
            }
        }
        return super.findClass(name);
    }*/

    private byte[] readFile(String pathname) throws FileNotFoundException, IllegalArgumentException, IOException {
        FileInputStream fin = new FileInputStream(new File(pathname));
        int available = fin.available();
        if (available > MAX_FILE_SIZE) {
            throw new IllegalArgumentException("Max allowed file size is " + MAX_FILE_SIZE + ". Found " + available + ".");
        }
        byte[] b = new byte[available];
        fin.read(b);
        return b;
    }

    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        try {
            return findClass(name);
        } catch (ClassNotFoundException ex) {
            return super.loadClass(name, resolve);
        }
    }
    public final int MAX_FILE_SIZE = 10000;
}
